#ifndef __demo_uhf_kenny_kfjiweiiur89u83r33iwuee3e__
#define __demo_uhf_kenny_kfjiweiiur89u83r33iwuee3e__

#include <hude/aio/context.hpp>

#include "plugs/virt-x2000/uhf/uhf.hpp"

#include "test/test.hpp"

namespace test
{
    using namespace pgl;

    //--------------------------------------------------------------------------------
    struct demo_uhf_t : public hude::test::case_t
    {
        enum { emCOUNT };

        using aio_t = hude::aio::aio_t<>;
        using uhf_t = pgl::uhf_t< aio_t >;

        aio_t aio_;
        bool  ret_;

        // 测试过程
        bool run() override;

        bool start();
        void stop();

    };

    //--------------------------------------------------------------------------------
    inline bool demo_uhf_t::run()
    {
        aio_ = hude::aio::context_t<>::aio();

        auto ret = aio_->run( [ = ]() {
            std::thread{ [=] () { ret_ = start(); stop(); } }.detach();
        } );

        return ret == 0 && ret_;
    }

    //--------------------------------------------------------------------------------
    inline void demo_uhf_t::stop()
    {
        this->aio_->cancel();
    }

    //--------------------------------------------------------------------------------
    inline bool demo_uhf_t::start()
    {
        /*********************************************************************
         * @brief 丢弃事件，丢弃无效串口数据时发生
         */
        auto on_droping = []( uhf_t::citr_t b, uhf_t::citr_t e )
        {
            log_war( "\t\t !!! droping bytes: %s", hude::utils::to_hex( &(*b), e - b ).c_str() );
        };

        /*********************************************************************
         * @brief 缓冲区输入事件，有串口数据输入时发生
         */
        auto on_input = []( uhf_t::citr_t b, uhf_t::citr_t e )
        {
            log_dug( "\t\t <<< input   bytes: %s", hude::utils::to_hex( &(*b), e - b ).c_str() );
        };

        /*********************************************************************
         * @brief 缓冲区输出事件，向串口输出数据时发生
         */
        auto on_output = []( uhf_t::citr_t b, uhf_t::citr_t e )
        {
            log_dug( "\t\t >>> output  bytes: %s", hude::utils::to_hex( &(*b), e - b ).c_str() );
        };

        uhf_t uhf( aio_, on_droping, on_input, on_output );

        if( ! uhf.open( "/tmp/dev/ttyUHF", 115200U ) )
        {
            log_err( "ERROR: Open uhf, uhf::open( \"/tmp/dev/ttyUHF\", 115200 ) == false" );
        }

        // 查询状态
        {
            auto state = uhf.state<>();

            if( state )
            {
                log_nte( "\t Get uhf state: %u", *state );
            } else {
                log_err( "ERROR: Get uhf state." );
            }
        }

        // 停止工作
        {
            auto ret = uhf.stop();

            if ( ret )
            {
                log_nte( "\t Request stop uhf." );
            } else {
                log_err( "ERROR: Request stop uhf." );
                return false;
            }
        }

        std::this_thread::sleep_for( std::chrono::seconds( 2 ) );

        // 设置功率
        {
            static const pgl::x2000::argument_t< uint8_t > ps[] = {  { 1U, 20U }, { 2U, 20U }, { 3U, 20U } };

            auto ret = uhf.set< x2000::mid_t::emSET_POWER >( ps, 3U );

            if ( ret )
            {
                log_inf( "\t Request set uhf power." );
            } else {
                log_err( "ERROR: Request set uhf power." );
                return false;
            }
        }

        // 查询功率
        {
            auto ret = uhf.get< x2000::mid_t::emGET_POWER >();

            if ( ret )
            {
                log_nte( "\t Request get uhf power( %hhu, %hhu, %hhu, %hhu ).",
                    ret->power( 0 ), ret->power( 1 ), ret->power( 2 ), ret->power( 3 ) );
            } else {
                log_err( "ERROR: Request get uhf power." );
                return false;
            }
        }

        // 设置频段
        {
            auto ret = uhf.set< x2000::mid_t::emSET_RF_BAND >();

            if ( ret )
            {
                log_inf( "\t Request set uhf rf_band." );
            } else {
                log_err( "ERROR: Request set uhf rf_band." );
                return false;
            }
        }

        // 查询频段
        {
            auto ret = uhf.get< x2000::mid_t::emGET_RF_BAND >();

            if ( ret )
            {
                log_nte( "\t Request get uhf band( %hhu ).", ret->result() );
            } else {
                log_err( "ERROR: Request get uhf band." );
                return false;
            }
        }

        // 设置频点
        {
            static const uint8_t fs[] = { 1, 2, 3, 4, 5 };

            auto ret = uhf.set< x2000::mid_t::emSET_RF_FREQ >( fs, 5U );

            if ( ret )
            {
                log_inf( "\t Request set uhf rf_freqs." );
            } else {
                log_err( "ERROR: Request set uhf rf_freqs." );
                return false;
            }
        }

        // 查询频段
        {
            auto ret = uhf.get< x2000::mid_t::emGET_RF_FREQ >();

            if ( ret )
            {
                log_nte( "\t Request get uhf freqs( %s ).", hude::utils::to_hex( ret->freqs(), ret->count() ).c_str() );
            } else {
                log_err( "ERROR: Request get uhf freqs." );
                return false;
            }
        }

        // 设置EPC基带参数
        {
            auto ret = uhf.set< x2000::mid_t::emSET_EPC >( 3U, 1U, 2U, 2U );

            if ( ret )
            {
                log_inf( "\t Request set uhf EPC." );
            } else {
                log_err( "ERROR: Request set uhf EPC." );
                return false;
            }
        }

        // 查询频点
        {
            auto ret = uhf.get< x2000::mid_t::emGET_EPC >();

            if ( ret )
            {
                log_nte( "\t Request mid_t::emGET_EPC( r: %hhu, q: %hhu, s: %hhu, t: %hhu ).",
                    ret->speed(), ret->qv(), ret->session(), ret->target() );
            } else {
                log_err( "ERROR: Request mid_t::emGET_EPC." );
                return false;
            }
        }

        // 设置驻留时长
        {
            auto ret = uhf.set< x2000::mid_t::emSET_HOLD >( 10U, 1U );

            if ( ret )
            {
                log_inf( "\t Request set uhf hold." );
            } else {
                log_err( "ERROR: Request set uhf hold." );
                return false;
            }
        }

        // 查询驻留时长
        {
            auto ret = uhf.get< x2000::mid_t::emGET_HOLD >();

            if ( ret )
            {
                log_nte( "\t Request mid_t::emGET_HOLD( a: %hu, f: %hu ).",
                    ret->ant(), ret->freq() );
            } else {
                log_err( "ERROR: Request mid_t::emGET_HOLD." );
                return false;
            }
        }

        // 设置标签过滤参数
        {
            auto ret = uhf.set< x2000::mid_t::emSET_TAG >( 20U, 1U );

            if ( ret )
            {
                log_inf( "\t Request set uhf TAG." );
            } else {
                log_err( "ERROR: Request set uhf TAG." );
                return false;
            }
        }

        // 查询标签过滤参数
        {
            auto ret = uhf.get< x2000::mid_t::emGET_TAG >();

            if ( ret )
            {
                log_nte( "\t Request mid_t::emGET_TAG( t: %hu, r: %hhu ).",
                    ret->time(), ret->rssi() );
            } else {
                log_err( "ERROR: Request mid_t::emGET_TAG." );
                return false;
            }
        }

        // 盘存标签
        {
            auto on_tag = []( const x2000::tag_t& tag )
            {
                log_nte( "\t # on_tag{ a: %u, f: %u, r: %u, tid: %s }", tag.ant, tag.freq, tag.rssi, hude::utils::to_hex( tag.epc, 0, 0 ).c_str() );
            };

            auto ret = uhf.scan< 0U >( on_tag, 0x01U, true );

            if ( ret )
            {
                log_nte( "\t Request mid_t::emREAD." );
            } else {
                log_err( "ERROR: Request read uhf tags." );
                return false;
            }
        }

        uhf.close();

        return true;
    }

    TEST_CASE_ADD( "uhf", demo_uhf_t, false );

} // namespace test

#endif // __demo_uhf_kenny_kfjiweiiur89u83r33iwuee3e__



